package com.gopay.scheduler.service.balance.impl;

import com.gopay.common.constants.acps.BalanceWarningOpen;
import com.gopay.common.constants.acps.BalanceWarningType;
import com.gopay.common.constants.cust.SMSType;
import com.gopay.common.constants.mail.MailLevel;
import com.gopay.common.constants.mail.MailTemplateType;
import com.gopay.common.cps.dao.acct.AcctBalanceWarningDao;
import com.gopay.common.domain.acps.AcctBalanceWarning;
import com.gopay.common.domain.cust.CustCorpInfo;
import com.gopay.common.domain.log.LogSMSSend;
import com.gopay.common.domain.mail.Send;
import com.gopay.common.order.dao.CommonQueryDAO;
import com.gopay.common.user.manager.CustCorpInfoQueryManager;
import com.gopay.remote.cps.mail.MailRemoteService;
import com.gopay.scheduler.dao.sms.LogSMSSendDAO;
import com.gopay.scheduler.service.balance.BalanceWarningService;
import com.gopay.sms.client.GopaySMSHttpClient;
import com.gopay.sms.common.constants.SMSAppId;
import com.gopay.sms.common.constants.SMSResCode;
import com.gopay.sms.common.domain.RequestVO;
import com.gopay.sms.common.domain.ResponseVO;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @classname:BalanceWarningServiceImpl
 * @description:余额预警提醒服务实现类
 * @date:2017/12/18/018
 * @author:PANSHICHAO
 * www.gopay.com.cn Inc.All rights reserved.
 */
@Service(value = "balanceWarningService")
public class BalanceWarningServiceImpl implements BalanceWarningService {
    @Resource(name="commonQueryDAO")
    private CommonQueryDAO commonQueryDAO;
    @Resource(name="acctBalanceWarningDao")
    private AcctBalanceWarningDao acctBalanceWarningDao;
    @Resource(name="mailRemoteService")
    private MailRemoteService mailRemoteService;
    protected Logger logger = LoggerFactory.getLogger(BalanceWarningServiceImpl.class);
    @Resource(name="custCorpInfoQueryManager")
    private CustCorpInfoQueryManager custCorpInfoQueryManager;
    @Resource(name="logSMSSendDAO")
    private LogSMSSendDAO logSMSSendDAO;
    private @Value("#{webProperties['portal.url']}") String portalUrl;

    private final int EMAIL_SEND_COUNT=3;

    @Override
    public List<Object[]> showAllCustCorpInfoByIsBalanceWarningConfig() {
        String sql = "select acct.cust_id,acct.acct_id from acct_balance_warning acct where acct.IS_BALANCE_WARNING_OPEN='01'";
        List<Object[]> resultList = commonQueryDAO.findBySql(sql);
        if(resultList == null ||resultList.size() == 0){
            return null;
        }else{
            return resultList;
        }
    }

    @Override
    public int showInfoCountByCustIdAndAcctIdAndBewteenDate(String acctId, Date startDate, Date endDate) {
        String sql = "select count(*) from acps_acct_trans_dtl where acct_id = :acctId and last_upd_tm >= :startDate and last_upd_tm < :endDate order by last_upd_tm desc";
        Map<String,Object> param = new HashMap<String,Object>(3);
        param.put("acctId",acctId);
        param.put("startDate",startDate);
        param.put("endDate",endDate);
        int resultCount  = commonQueryDAO.findCountBySql(sql,param);
        return resultCount;
    }

    @Override
    public AcctBalanceWarning showAllAcctBalanceWarningInfoByAcctId(String acctId) {
        List<AcctBalanceWarning> resultList = acctBalanceWarningDao.showAllBalanceWarningInfoByAcctId(acctId);
        if(resultList == null){
            return null;
        }else{
            return resultList.get(0);
        }
    }

    @Override
    public void sendBalanceWarningToEmailOrPhone(AcctBalanceWarning acctBalanceWarning) {
        if(BalanceWarningOpen.IS_OPEN.value.equals(acctBalanceWarning.getBalanceWarningOpen())){
            if(BalanceWarningType.BY_PHONE.value.equals(acctBalanceWarning.getBalanceWarningType())){
                sendMoblieInfo(acctBalanceWarning);
            }else if (BalanceWarningType.BY_EMAIL.value.equals(acctBalanceWarning.getBalanceWarningType())){
                sendEmailInfo(acctBalanceWarning);
            }else if(BalanceWarningType.BY_ALL.value.equals(acctBalanceWarning.getBalanceWarningType())) {
                sendMoblieInfo(acctBalanceWarning);
                sendEmailInfo(acctBalanceWarning);
            }
        }
    }

    @Override
    public BigDecimal showNowsAcctQuotaInfoByAcctIdAndBetweenDate(String acctId, Date startDate, Date endDate) {
        String sql ="select ACCT_ID,CUR_BAL_AFTER_TRANS,LAST_UPD_TM from ACPS_ACCT_TRANS_DTL where ACCT_ID=:acctId and last_upd_tm >= :startDate and last_upd_tm < :endDate order by LAST_UPD_TM desc";

        Map<String,Object> param = new HashMap<String,Object>(3);
        param.put("acctId",acctId);
        param.put("startDate",startDate);
        param.put("endDate",endDate);
        List<Object[]> resultList = commonQueryDAO.findBySql(sql,param);
        if(resultList == null || resultList.size() ==0){
            return new BigDecimal("0.00");
        }else{
            Object[] objects = resultList.get(0);
            Date nowDate = (Date)objects[2];
            if(nowDate.getTime()<=endDate.getTime()&&nowDate.getTime()>=startDate.getTime()){
                return new BigDecimal(objects[1].toString());
            }
        }
        return new BigDecimal("0.00");
    }

    private void sendMoblieInfo(AcctBalanceWarning acctBalanceWarning){
        int phoneSplitIndex = acctBalanceWarning.getBalanceWarningPhone().indexOf(",");
        if(phoneSplitIndex !=-1){
            String [] phoneItem = acctBalanceWarning.getBalanceWarningPhone().split(",");
            sendMobileSMS(phoneItem[0],SMSType.BALANCE_WARNING_NOTIFY,3,SMSAppId._90001,acctBalanceWarning);
            sendMobileSMS(phoneItem[1],SMSType.BALANCE_WARNING_NOTIFY,3,SMSAppId._90001,acctBalanceWarning);
        }else{
            sendMobileSMS(acctBalanceWarning.getBalanceWarningPhone(),SMSType.BALANCE_WARNING_NOTIFY,3,SMSAppId._90001,acctBalanceWarning);
        }
    }

    private void sendEmailInfo(AcctBalanceWarning acctBalanceWarning){
        Date [] dates = getStartDateAndEndDate();
        int emailSplitIndex = acctBalanceWarning.getBalanceWarningEmail().indexOf(",");
        if(emailSplitIndex != -1){
            String [] emailItem = acctBalanceWarning.getBalanceWarningEmail().split(",");
            List<Object[]> resultList = showSendsEmailByReceivers(emailItem[0],dates[0],dates[1]);
            int resultCountEmail1 = showSendEmailCount(resultList,acctBalanceWarning.getAcctID());
            if(resultCountEmail1<EMAIL_SEND_COUNT){
                sendEmail(emailItem[0],acctBalanceWarning.getCustID(),acctBalanceWarning.getAcctID(),acctBalanceWarning.getBalanceWarningQuota());
            }else{
                logger.error("今日通知邮件已经发送满3次，不再发送");
            }
            List<Object[]> resultList1 = showSendsEmailByReceivers(emailItem[1],dates[0],dates[1]);
            int resultCountEmail2 = showSendEmailCount(resultList1,acctBalanceWarning.getAcctID());
            if(resultCountEmail2<EMAIL_SEND_COUNT){
                sendEmail(emailItem[1],acctBalanceWarning.getCustID(),acctBalanceWarning.getAcctID(),acctBalanceWarning.getBalanceWarningQuota());
            }else{
                logger.error("今日通知邮件已经发送满3次，不再发送");
            }
        }else{
            List<Object[]> resultList = showSendsEmailByReceivers(acctBalanceWarning.getBalanceWarningEmail(),dates[0],dates[1]);
            int resultCountEmail = showSendEmailCount(resultList,acctBalanceWarning.getAcctID());
            if(resultCountEmail<EMAIL_SEND_COUNT){
                sendEmail(acctBalanceWarning.getBalanceWarningEmail(),acctBalanceWarning.getCustID(),acctBalanceWarning.getAcctID(),acctBalanceWarning.getBalanceWarningQuota());
            }else{
                logger.error("今日通知邮件已经发送满3次，不再发送");
            }
        }
    }
    private int sendEmail(String email,String custId,String accId,BigDecimal balanceQuota){
        int result =1;
        Send send = new Send();
        send.setReceivers(email);
        send.setTemplate(MailTemplateType.TOUCH_BALANCE_WARNING_NOTIFY.value);
        send.setLevel(MailLevel.MID);
        Map<String,Object> json = new HashMap<String,Object>(3);
        CustCorpInfo custCorpInfo = custCorpInfoQueryManager.getByCustId(custId);
        json.put("replaceBalanceWarningCorpName",custCorpInfo.getCorpName());
        json.put("replaceBalanceWarningAcctId", accId);
        json.put("replaceBalanceWarningQuoate", balanceQuota);
        json.put("replacethistotheLogoAddr", portalUrl);
        send.setContent(JSONObject.fromObject(json).toString());
        int i = mailRemoteService.addMailTask(send);
        logger.error("邮件发送结果为:"+i);
        if(i !=0){
            result += 1;
        }
        return result;
    }
    private int sendMobileSMS(String mobileNo, SMSType smsType, int smsMaxCount,SMSAppId appid,AcctBalanceWarning acctBalanceWarning) {
        String lastAcctId = acctBalanceWarning.getAcctID().substring(9);
        BigDecimal bigDecimal = acctBalanceWarning.getBalanceWarningQuota();
        String content="您尾号为"+lastAcctId+"的账户\n可用额度已不足"+bigDecimal+"元，请登录国付宝查看。此消息每日最多发送3次，30分钟内不再提醒。";
        //调用短信网关
        logger.info("进入发送短信方法.........");
        if(smsMaxCount != 0){
            int count = logSMSSendDAO.findToDayCountByMobileNum(mobileNo, smsType.value,acctBalanceWarning.getAcctID());
            logger.info("当天已经发送短信次数 count = " + count);
            logger.info("当天最大发送短信次数 smsMaxCount = " + smsMaxCount);
            if(smsMaxCount >count){
                logger.info("调用发短信方法");
                return this.sendSMS(mobileNo, smsType,appid,content,acctBalanceWarning.getAcctID());
                //return 1;
            }else{
                logger.info("次数超限返回3");
                return 3;
            }
        }else{
            return this.sendSMS(mobileNo, smsType, appid,content,acctBalanceWarning.getAcctID());
            //return 1;
        }

    }
    private int sendSMS(String mobileNo, SMSType smsType,SMSAppId appid,String content,String acctId){
        //调用短信网关
        RequestVO req = new RequestVO();
        req.setMobile(mobileNo);
        req.setAppId(appid.value);
        req.setContent(content);
        ResponseVO resposeVo = GopaySMSHttpClient.getInstance().createVerificationCode(req);
        if(resposeVo.getStatusCode().equals(SMSResCode.SMS_DEND_SUCCESS.value)){
            logSMSSendDAO.save(buildLog(mobileNo,smsType,acctId));
            logger.info("短信返回Msg = " + resposeVo.getMessage()+"短信返回code = " + resposeVo.getStatusCode());
            return 1;
        }else{
            logger.info("短信返回Msg = " + resposeVo.getMessage()+"短信返回code = " + resposeVo.getStatusCode());
            return 2;
        }
    }
    private LogSMSSend buildLog(String mobileNo, SMSType smsType,String acctId){
        LogSMSSend log = new LogSMSSend();
        Date date = new Date();
        log.setMobileNum(mobileNo);
        log.setMobileID(smsType.value);
        log.setSendTime(date);
        log.setLastUpdTs(date);
        log.setCreatedTs(date);
        log.setRemarks(acctId);
        return log;
    }

    private List<Object[]> showSendsEmailByReceivers(String email,Date startDate,Date endDate){
        String sql ="select id,receivers,template,content from mail_send where TEMPLATE='touchBalanceWarningInfo' and last_up_date >=:startDate and last_up_date <:endDate and receivers = :receivers ";
        Map<String,Object> param = new HashMap<String,Object>(3);
        param.put("receivers",email);
        param.put("startDate",startDate);
        param.put("endDate",endDate);
        List<Object[]> resultList  =commonQueryDAO.findBySql(sql,param);
        if(resultList == null){
            return null;
        }else{
            return resultList;
        }
    }
    @Override
    public Date[] getStartDateAndEndDate(){
        Date[] resultDate = new Date[2];
        Date time = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String timeStr = format.format(time);
        SimpleDateFormat transfer = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date start = null;
        Date end = null;
        try {
            start = transfer.parse(timeStr+" 00:00:00");
            end = transfer.parse(timeStr+" 23:59:59");
            resultDate[0]=start;
            resultDate[1]=end;
        } catch (Exception e) {
            logger.error("发送余额预警通知出现异常："+e);
        }
        return resultDate;
    }

    @Override
    public void updateBalanceNotifyQuota(AcctBalanceWarning acctBalanceWarning) {
        if(acctBalanceWarning == null){
            return;
        }
        acctBalanceWarningDao.update(acctBalanceWarning);
    }

    private int showSendEmailCount(List<Object[]> resultList,String acctId){
        int sendCount = 0;
        if(resultList == null || resultList.size()==0){
            sendCount = 0;
        }
        else{
            for(Object[] obj : resultList){
                String content = obj[3].toString();
                Map map = (Map)JSONObject.fromObject(content);
                String resultAcctId = map.get("replaceBalanceWarningAcctId").toString();
                if(StringUtils.equals(acctId,resultAcctId)){
                    sendCount = sendCount+1;
                }
                else
                {
                    continue;
                }
            }
        }
        return sendCount;
    }
}
